_Pragma("once");

#include <string>
#include <vector>

#include "SingletonTemplate.h"
#include "LoopStatusListener.h"
#include "ExtendDeviceType.h"
#include "ExtendDevice.h"
#include "MultiPortDeviceManager.h"
#include "LoopControlInfo.h"
#include "TaskScheduler.h"
#include "AcSwitchDetector.h"
#include "ConfigManager.h"
#include "LoopController.h"
#include "NetworkListener.h"


class CurrentVoltageManager;

constexpr std::time_t CORRELATION_DETECT_DELAY{7};

constexpr std::time_t AUO_COMMAND_DELAY_APPEND = 3;

constexpr std::time_t OFFLINE_RECOVER_DELAY = 300;

constexpr std::time_t DEFAULT_MANUAL_MODE_KEEP_TIME = 600;

/**
 * 回路控制管理类
 *@author lizb
 */
class LoopManager : public MultiPortDeviceManager<LoopController>, public NetworkListener, protected LoopStatusListener {
public:
    friend class SingletonTemplate<LoopManager>;

    using super = MultiPortDeviceManager<LoopController>;

    void closeAutoLoopStatus(const LoopCommandType commandType, void* opaque) {
        updatePortCount();
        LoopControlInfoPtr ploopControlInfo(new(mpTimedLoopControlInfo->length) LoopControlInfo{*mpTimedLoopControlInfo}, LoopControlInfo::releaseMemory);
        ploopControlInfo->commandType = commandType;
        changeAutoLoopStatus(ploopControlInfo);
    }

    /**
    * 根据command修改回路状态（自动操作）
    *
    * @param command
    * @return
    */
    void changeAutoLoopStatus(const LoopControlInfoPtr& command, const std::time_t delaySeconds = 0);

    /**
     * 更改单个回路状态,只对应手动操作 附带状态
     * 手动操作只需要指定回路序号 不能指定回路状态
     * @param status 需要变更的状态
     * @param index  需要更改的回路序号
     * @return
     */
    bool changeManualLoopStatus(const size_t index, const LoopStatus status = LoopStatus::NEXT_MANUAL_STATUS);





    /**
     * 还原到自动模式
     */
    void returnToAutoMode();

    void offlineCircleCommand();


    /**
     * 获取手动指令结束 还剩余的时间
     * @return
     */
    std::time_t getManualModeRemainTime() {
        std::time_t remainTime = mmanualModeKeepTime;
        if (0 != manualModalStopTime) {
            remainTime = (manualModalStopTime - std::time(nullptr));
        }
        return remainTime;
    }




    LoopControlInfoPtr getLoopStatus() {
        std::string buffer;
        getLoopStatus(buffer);
        std::string::size_type size = buffer.size();
        return LoopControlInfoPtr(new(size) LoopControlInfo(reinterpret_cast<const LoopStatus* const >(buffer.data()), size), LoopControlInfo::releaseMemory);
    }


    /**
     * 获取当前回路状态(0/1)
     *
     * @return
     */
    std::string& getLoopStatus(std::string& buffer) {
        buffer.reserve(mpControllers->size() * (MDConst::DEFAULT_INTERNAL_LOOP_COUNT << 3));
        LoopController* pLoopController;
        ExtendDevicePtr extendDevicePtr;
        for (ExtendDeviceWeakPtr& loopDeviceWeakPtr : *mpControllers) {
            extendDevicePtr = loopDeviceWeakPtr.lock();
            if (!extendDevicePtr) {
                continue;
            }
            pLoopController = static_cast<LoopController*> (&*extendDevicePtr);
            buffer.append(reinterpret_cast<std::string::value_type*> (pLoopController->mloopStatusArray), pLoopController->mportCount);
        }

        return buffer;
    }

    size_t updatePortCount() {
        size_t length = super::updatePortCount();
        mpTimedLoopControlInfo.reset(new(length) LoopControlInfo(length, LoopStatus::AUTO_OFF), LoopControlInfo::releaseMemory);

        return length;
    }

    bool updateLoopControllerConfig(const LoopControllerConfigInfo& loopControllerConfig);

protected:


    bool onLoopChanged(const size_t index, const LoopStatus status) override {
        DateTimeUtility::ClockTime_t triggerTime{(std::time(nullptr) + CORRELATION_DETECT_DELAY) * DateTimeUtility::ClockTime_t::period::den};

        TaskRecord* ptaskRecord = new TaskRecord(TaskletInfo{std::bind(&LoopManager::validateCorrelationStatus, this), nullptr}, triggerTime, tick_count_t{CORRELATION_DETECT_DELAY * DateTimeUtility::ClockTime_t::period::den}, ETT_CIRCLE);
        mtaskScheduler.makeOnlyOneTask(mwptrSwitchStatusTaskRecord, ptaskRecord);

        return mpLoopStatusListener->onLoopChanged(index, status);
    }


    bool onLoopChanged(const LoopControlInfoPtr command) override {
        DateTimeUtility::ClockTime_t triggerTime{(std::time(nullptr) + CORRELATION_DETECT_DELAY) * DateTimeUtility::ClockTime_t::period::den};
        TaskRecord* ptaskRecord = new TaskRecord(TaskletInfo{std::bind(&LoopManager::validateCorrelationStatus, this), nullptr}, triggerTime, tick_count_t{CORRELATION_DETECT_DELAY * DateTimeUtility::ClockTime_t::period::den}, ETT_CIRCLE);
        mtaskScheduler.makeOnlyOneTask(mwptrSwitchStatusTaskRecord, ptaskRecord);

        return  mpLoopStatusListener->onLoopChanged(command);
    }


    void offline(INetwork* const network) override;

    void online(INetwork* const network) override;


  bool  validateCorrelationStatus();

private:
    LoopManager();

    LoopManager(LoopManager&&) = delete;
    LoopManager(const LoopManager&) = delete;

public:

    /**	手动指令结束时间,为0时即没有手动指令在执行*/
    volatile std::time_t manualModalStopTime = 0;

    /**
    * 手动模式持续时间s (默认时间3600s)
    * */
     std::time_t mmanualModeKeepTime = DEFAULT_MANUAL_MODE_KEEP_TIME;

    /**
     * 监听回路改变的监听器
     */
    LoopStatusListener* mpLoopStatusListener;

    LoopControlInfoPtr mpTimedLoopControlInfo;

    TaskRecordPtr::weak_type mwptrOfflineTaskRecord;
    TaskRecordPtr::weak_type mwptrTaskRecord;
    TaskRecordPtr::weak_type mwptrSwitchStatusTaskRecord;

    TaskScheduler& mtaskScheduler;

    ConfigManager& mconfigManager;

    std::vector<ExtendDeviceWeakPtr>& mswitchDetectors;
    std::vector<ExtendDeviceWeakPtr>& macDetectors;

    CurrentVoltageManager& mcurrentVoltageManager;
    LoopControllerConfigInfo mloopControllerConfig;

    uint8_t mpowerAlertSent = 0;
    uint8_t mcircuitAlertSent = 0;

    volatile LoopCommandType mrunningCommandType = LoopCommandType::NONE_COMMAND;
};

using LoopManagerSingleton = SingletonTemplate<LoopManager>;
